/**
 * @file optional.hpp
 * @author yangjian (1171267147@qq.com)
 * @brief Optional类实现
 * @version 0.1
 * @date 2025-07-15
 * 
 * @copyright Copyright (c) 2025
 * 
 */
#include <stdexcept>
#include <type_traits>

/**
 * @brief Optioal类，当没有存储值时，进行bool检查将返回false
 * 
 * @tparam T 
 */
template <typename T>
class Optional {
    // 使用typename用来解决模板类型未决名问题
    // aligned_storage<>用来保证就地构造时，存储空间与类型T的内存对齐一致
    using DataType = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;

public:
    Optional() {}
    Optional(const T& val) { Create(val); }
    Optional(const Optional& other) {
        if (other.IsInit()) {
            Assign(other);
        }
    }
    ~Optional() { Destroy(); }

    // 通过使用不定模板参数来满足不同类型的构造函数的形参需求
    template <typename... Args>
    void Emplace(Args&&... args) {
        Destroy();
        // 使用完美转发，避免数据拷贝
        Create(std::forward<Args>(args)...);
    }

    bool IsInit() const { return hasInit_; }

    explicit operator bool() const { return IsInit(); }

    T& operator*() const {
        if (IsInit()) {
            return *((T*)(&data_));
        }
        throw std::runtime_error("Optional is not init");
    }

private:
    template <typename... Args>
    void Create(Args&&... args) {
        // 通过new进行就地构造
        new (&data_) T(std::forward<Args>(args)...);
        hasInit_ = true;
    }

    void Destroy() {
        if (IsInit()) {
            // 显示调用被构造对象的析构函数来销毁对象
            // 不能使用delete，因为就地构造的对象不涉及堆内存分配，实际上使用的是data_的内存
            reinterpret_cast<T*>(&data_)->~T();
            hasInit_ = false;
        }
    }

    void Assign(const Optional& other) {
        if (other.IsInit()) {
            Copy(other.data_);
            hasInit_ = true;
        } else {
            Destroy();
        }
    }

    void Copy(const DataType& val) {
        Destroy();
        new (&data_) T(*(reinterpret_cast<T*>(&val)));
    }

private:
    bool     hasInit_ = false;
    DataType data_;
};